<?php
/**
 * Created by PhpStorm.
 * User: lhl
 * Date: 2020/10/20
 * Time: 10:00
 * Features:角色管理
 */

namespace app\adminapiv3\model;


use app\common\service\StringHelper;
use think\Exception;
use think\Db;

class ServerUserGroupModel extends BaseModel
{
    //只读字段
    protected $readonly = ['is_root'];

    /**
     * 搜索器
     * @field role 角色名称
     */
    public function searchRoleAttr($query, $value, $data){
        $value = trim($value);
        if(strlen($value)){
            $query->where('role','like',"%{$value}%");
        }
    }

    /**
     * 搜索器
     * @field description 角色描述
     */
    public function searchDescriptionAttr($query, $value, $data){
        $value = trim($value);
        if(strlen($value)){
            $query->where('description','like',"%{$value}%");
        }
    }

    /**
     * 搜索器
     * @field create_time 创建时间
     */
    public function searchCreateTimeAttr($query, $value, $data){
        $value = trim($value);
        if(strlen($value)){
            $startTime = strtotime($value);
            $endTime = $startTime + 86399;
            $query->whereBetweenTime('create_time',$startTime,$endTime);
        }
    }

    /**
     * 查询角色列表
     * @param array $search 搜索参数
    */
    public function getList($search = [])
    {
        return $this->withSearch(['role','description','create_time'],$search)->paginate()->toArray();
    }

    /**
     * 添加角色
     * @param array $param 表单数据
    */
    public function addGroup($param){
        //记录操作日志
        global $logArray;
        $logArray = array(
            'content' => '添加角色',
        );

        //补充字段
        $param = array_merge($param,[
            'is_root' => 0,
            'create_time' => time()
        ]);

        //保存角色数据
        if(!$this->insert($param)){
            $this->setError($this->CODE_FAIL,'操作失败');
            return false;
        }

        //记录操作日志
        $logArray['new_info'] = "角色名称：{$param['role']}；角色描述：{$param['description']}；".PHP_EOL;
        return true;
    }

    /**
     * 修改角色
     * @param array $param 表单数据
     */
    public function modifyGroup($param){
        //记录操作日志
        global $logArray;
        $logArray = array(
            'content' => '修改角色',
        );

        //查询信息
        $info = $this->where('id',$param['id'])->findOrEmpty()->toArray();
        if(!$info){
            $this->setError($this->CODE_FAIL,'角色不存在');
            return false;
        }

        //补充字段
        $param = array_merge($param,[
            'update_time' => time()
        ]);

        try{
            //保存角色表
            $this->update($param,['id' => $param['id']]);
        }catch (Exception $e){
            $this->setError($this->CODE_FAIL,'操作失败');
            return false;
        }

        //记录操作日志
        $logArray['new_info'] = "角色名称：{$param['role']}；角色描述：{$param['description']}；".PHP_EOL;
        $logArray['old_info'] = "角色名称：{$info['role']}；角色描述：{$info['description']}；";
        return true;
    }

    /**
     * 批量删除角色
     * @param string $ids 角色id逗号隔开字符串
    */
    public function delGroup($ids){
        //记录操作日志
        global $logArray;
        $logArray = array(
            'content' => '删除角色',
        );

        //查询角色信息
        $list = $this->where('id','in',$ids)->select()->toArray();
        if(!$list){
            $this->setError($this->CODE_FAIL,'数据不存在');
            return false;
        }
        $ids = array_column($list,'id');
        $isRoot = array_unique(array_column($list,'is_root'));
        //不能删除超级管理员组
        if($isRoot != [0]){
            $this->setError($this->CODE_FAIL,'不能删除超级管理员角色');
            return false;
        }

        //角色下有用户,则不能删除
        $userGroupMappingModel = new ServerUserGroupMappingModel();
        $countData = $userGroupMappingModel->getGroupUserListCount($ids);
        if (array_unique(array_column($countData,'num')) != [0]) {
            $this->setError($this->CODE_FAIL,'所选角色下存在用户,无法删除');
            return false;
        }

        //统计本次删除数量
        $count = count($ids);

        //保存数据
        $this->startTrans();
        try{
            //删除角色表数据
            if (!$this->where('id','in',$ids)->delete()) {
                $this->rollback();
                $this->setError($this->CODE_FAIL,'删除失败');
                return false;
            }

            //删除用户-角色中间表数据
            $userGroupMappingModel->where('group_id','in',$ids)->delete();

            //删除角色-权限中间表数据
            $groupAuthMappingModel = new ServerGroupAuthMappingModel();
            $groupAuthMappingModel->where('group_id','in',$ids)->delete();

            $this->commit();
            //记录日志
            $logArray['old_info'] = "一共删除{$count}个角色；角色名为".implode(',',array_column($list,'role'));
            return true;
        }catch (Exception $e){
            $this->rollback();
            $this->setError($this->CODE_FAIL,'删除失败');
            return false;
        }
    }


    /**
     * 根据角色id查询单个角色及其权限数据
     * @param int   $id     角色id
     * @param array $where  附加查询条件
     */
    public function getGroupInfo($id,$where = []){
        $where = array_merge($where,[
            'id' => $id
        ]);
        //查询角色
        $info = $this->where($where)->findOrEmpty()->toArray();

        //查询该角色权限数据
        $info['auth'] = \model('ServerGroupAuthMapping')->alias('ra')
            ->join('server_permission a','ra.auth_id=a.id','left') //关联查询权限
            ->where([
                'ra.group_id' => $id, //该角色的权限
            ])
            ->field('ra.auth_id,a.*')
            ->select()->toArray();
        foreach ($info['auth'] as $key => $item){
            unset($info['auth'][$key]['id']);
        }

        $info['auth_ids'] = implode(',',array_column($info['auth'],'auth_id'));
        return $info;
    }

    /**
     * 给角色授权
     * @param array $param 表单数据
    */
    public function auth($param){
        //记录操作日志
        global $logArray;
        $logArray = array(
            'content' => '角色授权',
        );

        //验证权限参数
        $authIdArr = \model('ServerPermission')->getAuthByIdStr($param['auth_ids'],'id,pid,level,path,name');
        $authNames = implode(',',array_column($authIdArr,'name'));
        $authIds = array_unique(array_column($authIdArr,'id'));
        if(count(explode(',',$param['auth_ids'])) != count($authIds)){
            $this->setError($this->CODE_FAIL,'所选权限已被删除,请刷新页面');
            return false;
        }

        //验证id,确定原本信息
        $info = $this->getGroupInfo($param['id']);
        if(!$info){
            $this->setError($this->CODE_FAIL,'数据不存在');
            return false;
        }
        //超级管理员组 不允许授权
        if($info['is_root']){
            $this->setError($this->CODE_FAIL,'超级管理员不允许分配权限');
            return false;
        }

        $oldAuthNames = implode(',',array_column($info['auth'],'name'));
        //勾选子权限的同时,也必须勾选其上级权限
        foreach ($authIdArr as $item){
            $map = [0,$item['id']];
            $ids = explode(',',$item['path']);
            //去掉ids中的等于0和节点本身id的元素 得到其上级id
            foreach ($ids as $k => $v){
                if(in_array($v,$map)){
                    continue;
                }
                if(!in_array($v,$authIds)){
                    $this->setError($this->CODE_FAIL,'勾选子权限的同时也必须勾选其上级权限');
                    return false;
                }

            }
        }

        //补全字段
        $roleAuth = [];
        foreach ($authIds as $item){
            $roleAuth[] = [
                'group_id' => $param['id'],
                'auth_id' => $item
            ];
        }

        //保存
        $this->startTrans();
        try{
            //将角色-权限中间表数据统一先删除再添加
           \model('ServerGroupAuthMapping')->where(['group_id' => $param['id']])->delete();

            if (!\model('ServerGroupAuthMapping')->insertAll($roleAuth)) {
                $this->setError($this->CODE_FAIL,'修改失败');
                return false;
            }

            $this->commit();

            //记录操作日志
            $logArray['new_info'] = "用户名组名：{$info['role']}；权限：{$authNames}";
            $logArray['old_info'] = "用户名组名：{$info['role']}；权限：{$oldAuthNames}";
            return true;
        }catch (Exception $e){
            $this->rollback();
            $this->setError($this->CODE_FAIL,'修改失败');
            return false;
        }

    }

    /**
     * 检测角色id合法性
     * @param array  $idArr      角色id数组
     */
    public function checkGroupId($idArr){
        $where = [
            ['id','in',$idArr],
        ];
        $count = $this->where($where)->count();
        return count($idArr) == $count ? true : false;
    }

}